package com.bsit.obu.ui;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;

import androidx.annotation.Nullable;

import com.bsit.obu.base.BaseApplication;
import com.google.android.material.tabs.TabLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;

import android.os.Handler;
import android.serialport.DeviceControlSpd;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.Toast;

import com.bsit.obu.R;
import com.bsit.obu.base.BaseActivity;
import com.bsit.obu.business.SocketBusiness;
import com.bsit.obu.callback.RequestCallBack;
import com.bsit.obu.constant.Constants;
import com.bsit.obu.fragment.CarFragment;
import com.bsit.obu.fragment.SystemFragment;
import com.bsit.obu.model.CarSecondPublicInfo;
import com.bsit.obu.utils.ActivityTask;
import com.bsit.obu.utils.ByteUtil;
import com.bsit.obu.utils.CommonUtil;
import com.bsit.obu.utils.MyLog;
import com.bsit.obu.utils.ToastUtils;
import com.speedata.libutils.DataConversionUtils;
import com.tianyuxinghang.sxmobileterm.bean.CardInformation;
import com.tianyuxinghang.sxmobileterm.bean.ObuSystemInformation;
import com.tianyuxinghang.sxmobileterm.constants.DSRCERROR;
import com.tianyuxinghang.sxmobileterm.model.MTSdkImp;


import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import speedatacom.a3310libs.PsamManager;
import speedatacom.a3310libs.inf.IPsam;

public class IssueActivity extends BaseActivity {
    private String obuSerialNum;

    @BindView(R.id.tabLayout)
    TabLayout tableLayout;
    @BindView(R.id.vp_content)
    ViewPager vp_content;
    private List<Fragment> fragmentList;
    private String[] titles = {"系统信息","车辆信息"};
    @BindView(R.id.more_iv)
    ImageView mMoreIv;              //菜单栏多图标

    private PopupWindow mPopView;

    private String psamCardNum = "";
    private int ret  = -1;
    private int psamflag = 1;

    private   byte[] data;


    //获取psam实例
    private IPsam psamIntance = PsamManager.getPsamIntance();
    private Handler handler = new Handler();
    @Override
    protected void initView() {
        setContentView(R.layout.activity_issue);
    }

    @Override
    protected void fillView() {
        super.fillView();
        titleTv.setText("电子标签联网激活");
        initFragmentList();
        for (int i = 0;i<titles.length;i++){
            tableLayout.addTab(tableLayout.newTab().setText(titles[i]));
        }
        vp_content.setAdapter(new MyAdapter(getSupportFragmentManager()));
        vp_content.setOffscreenPageLimit(0);
        tableLayout.setupWithViewPager(vp_content);
        try {
            psamIntance.initDev("ttyMT1",115200, DeviceControlSpd.PowerType.NEW_MAIN,this,12,16,46);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
      //  MTSdkImp.getInstance(this).initSDK("/dev/ttyMT0", 115200,  null );

        // Android 6.0动态请求权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE
                    , Manifest.permission.READ_EXTERNAL_STORAGE};
            for (String str : permissions) {
                if (checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    requestPermissions(permissions, 111);
                    break;
                }
            }
        }
    }

    private void openPasm() {
        data = psamIntance.PsamPower(IPsam.PowerType.Psam1);
        MyLog.e(MyLog.TAG, "openPasm : " + psamflag+" "+DataConversionUtils.byteArrayToString(data));
        if (data == null) {
            psamflag = 2;
            data = psamIntance.PsamPower(IPsam.PowerType.Psam2);
            MyLog.e(MyLog.TAG, "openPasm : " + psamflag+" "+DataConversionUtils.byteArrayToString(data));
        }

    }

    @OnClick(R.id.read_btn)
    public void read_btn(){
        if(!isNetworkAvailable(this)){
            ToastUtils.showToast(this,"请检查网络连接是否正常");
            return;
        }
        openPasm();
        if(data!=null){
            getPasmCardNum(psamflag);
        }else{
            ToastUtils.showToast(this,"未插入psam卡！");
        }

    }


    @OnClick(R.id.active_btn)
    public void active_btn(){
        if(TextUtils.isEmpty(obuSerialNum)){
            ToastUtils.showToast(this,"请先读取系统信息！");
            return;
        }
        goActivation();

    }

    /**
     * 获取pasm卡号
     * @param psamflag 卡槽号 1 卡槽1   2 卡槽2
     */
    private void getPasmCardNum(int psamflag) {
        String[] commands = new String[]{"00B095000E"};
        sendApdu(psamflag,commands);
        String value = commands[commands.length-1];
        if (!TextUtils.isEmpty(value)&&value.endsWith("9000")) {
            psamCardNum = commands[commands.length-1].substring(4, 20);
        }else{
            ToastUtils.showToast(this,"获取pasm卡信息异常");
            return;
        }
        MyLog.e(MyLog.TAG, "psamCardNum : " + psamCardNum);
        indetify("10",psamCardNum,psamflag);

    }
    private void  sendApdu(int psamflag,String[] commands){
        if(commands==null){
            throw  new NullPointerException("commands is null");
        }
        String result = "";
        for(int i = 0; i<commands.length ;i++){
            if (psamflag == 1) {
                try {
                    data = psamIntance.WriteCmd(DataConversionUtils
                            .HexString2Bytes(commands[i]), IPsam.PowerType.Psam1);
                    result = DataConversionUtils.byteArrayToString(data);
                    if(result.startsWith("61")) {
                        String var = "00C00000" + result.substring(2);
                        data = psamIntance.WriteCmd(DataConversionUtils
                                .HexString2Bytes(var), IPsam.PowerType.Psam1);
                        result = DataConversionUtils.byteArrayToString(data);
                    }
                    commands[i] = result ;
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

            } else if (psamflag == 2) {
                try {
                    data = psamIntance.WriteCmd(DataConversionUtils
                            .HexString2Bytes(commands[i]), IPsam.PowerType.Psam2);
                    result = DataConversionUtils.byteArrayToString(data);
                    MyLog.e(MyLog.TAG, "sendApdu : " + result);
                    if(result.startsWith("61")) {
                        String var = "00C00000" + result.substring(2);
                        data = psamIntance.WriteCmd(DataConversionUtils
                                .HexString2Bytes(var), IPsam.PowerType.Psam2);
                        result = DataConversionUtils.byteArrayToString(data);
                    }

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            MyLog.e(MyLog.TAG, "sendApdu : " + result);
            commands[i] = result ;
        }
    }


    /**
     * 请求身份认证请求
     * @param cmd AST：0x10
     * @param data pasm卡号：43011936286100000001
     */
    private void indetify(String cmd,String data,int psamflag) {
        showDialog("初始化身份信息...");
        MyLog.d(MyLog.TAG, "初始化身份信息-------------->");
        SocketBusiness.getInstance().requestData(cmd,data,new RequestCallBack(){
            @Override
            public void next(String statusCode,String data) {
                dismissDialog();
                //09080E0D0E01000E BFAC 5F
                if(!TextUtils.isEmpty(data)){
                    get3DesData(data.substring(0,16),psamflag);
                }
            }
            @Override
            public void error(String statusCode,String error) {
                dismissDialog();
                //失败：错误码
                //错误码类型：
                //0x0001:非有效psam卡
                //0x0002:查询白名单psam卡失败
                if(statusCode.equals("0001")){
                   showCommonDialog("非有效psam卡");
                 //   ToastUtils.showToast(IssueActivity.this,"非有效psam卡");
                }else if(statusCode.equals("0002")){
                   showCommonDialog("查询白名单psam卡失败");
                }else if(statusCode.equals(Constants.ERROR_CODE)){
                   showCommonDialog("服务异常，请稍后再试！");
               }
            }
        });
    }


    /**
     *
     * @return  加密数据
     */
    private void get3DesData(String rand,int card_slot) {
        String[] commands = new String[]{"00A4000002DF01","801A080100","80FA000008"+rand};
        sendApdu(card_slot,commands);
        if (!TextUtils.isEmpty(commands[commands.length-1])) {
            psamCardNum = commands[commands.length-1].substring(0,16);
            confrimPsamCard("12", commands[commands.length-1].substring(0,16));
        }else{
            ToastUtils.showToast(this,"加密失败");
            return;
        }

    }


    /**
     * Psam卡密钥核实请求
     * @param cmd  AST：0x12
     * @param data 对随机数进行3DES加密
     */
    private void confrimPsamCard(String cmd,String data){
        showDialog("身份认证中...");
        MyLog.d(MyLog.TAG, "Psam卡密钥核实请求-------------->");
        SocketBusiness.getInstance().requestData(cmd,data,new RequestCallBack(){
            @Override
            public void next(String statusCode,String data) {
                dismissDialog();
                readSystemInfo();
            }

            @Override
            public void error(String statusCode,String error) {
                dismissDialog();
                /*失败：错误码
                错误码类型：
                0x0001：身份认证核实不通过
                0x0002：加密时出错
                0x0003：尚未进行身份手持机认证*/

                if(statusCode.equals("0001")){
                    showCommonDialog("身份认证核实不通过");
                }else if(statusCode.equals("0002")){
                    showCommonDialog("加密时出错");

                }else if(statusCode.equals("0003")){
                    showCommonDialog("尚未进行身份手持机认证");
                }else if(statusCode.equals(Constants.ERROR_CODE)){
                    showCommonDialog("服务异常，请稍后再试！");
                }

            }
        });

    }

    private ObuSystemInformation obuSystemInformation;
    private CardInformation cardInformation;
    /**
     * 读取系统信息
     */
    private void readSystemInfo() {
        MyLog.d(MyLog.TAG, "obu信息读取中，请稍后-------------->");
        obuSystemInformation = new ObuSystemInformation();
        cardInformation = new CardInformation();

        int ret =  MTSdkImp.getInstance(this).searchObu(obuSystemInformation,null);
        if(ret==0){
            obuSerialNum = obuSystemInformation.getSerialNumber();
            if(TextUtils.isEmpty(obuSerialNum)){
                showCommonDialog("未检测到标签");
            }else{
                updateSystemInfo(obuSystemInformation);
                String vehicleInfo = MTSdkImp.getInstance(this).obuGetSecure("1234567891234567");
                String data = obuSerialNum + vehicleInfo;
                decryptCarInfo("20", data);
            }

        }else if(ret== DSRCERROR.PLEASE_POWER_ON.code){
            showCommonDialog("请先上电");
        }else{
            showCommonDialog("唤醒失败");
        }
    }

    /**
     * 车辆信息解密请求
     * @param cmd AST：0x20
     * @param data
     * DATA部分：
     * 字段	长度(字节)	说明
     * 分散因子	8	OBU合同序列号
     * 车辆信息（密文）	N	GetSecure返回的密文信息。
     */
    private void decryptCarInfo(String cmd,String data){
        showDialog("正在联网解析车辆信息，请稍后...");
        MyLog.d(MyLog.TAG, "正在联网解析车辆信息，请稍后-------------->");
        SocketBusiness.getInstance().requestData(cmd,data,new RequestCallBack(){
            @Override
            public void next(String statusCode,String data) {
                dismissDialog();
                CarSecondPublicInfo carSecondPublicInfo =  CommonUtil.parseCarPalteInfo(ByteUtil.hexStr(data.substring(18)));
                ((CarFragment)fragmentList.get(1)).updateUI(carSecondPublicInfo);
            }

            @Override
            public void error(String statusCode,String error) {
                dismissDialog();
              /*  失败：错误码
                错误码类型：
                0x0001：已激活过车辆，且超出了可重激活时间
                0x0002：未登记车辆
                0x0003：解密失败*/
                if(statusCode.equals("0001")){
                    CarSecondPublicInfo carSecondPublicInfo =  CommonUtil.parseCarPalteInfo(ByteUtil.hexStr(error.substring(18)));
                    ((CarFragment)fragmentList.get(1)).updateUI(carSecondPublicInfo);
                    showCommonDialog("已激活过车辆，且超出了可重激活时间");
                }else if(statusCode.equals("0002")){
                    // error = "57809D77DF06C74439CFE64143363337370000000000010C01012C969632640064000005424D5700000000000000000000000000424B3030313230000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFD5F";
                 //   MyLog.e(MyLog.TAG,"车辆信息明文数据 len ===" + error.length() + "  data----" + error);
                    CarSecondPublicInfo carSecondPublicInfo =  CommonUtil.parseCarPalteInfo(ByteUtil.hexStr(error.substring(18)));
                    ((CarFragment)fragmentList.get(1)).updateUI(carSecondPublicInfo);
                    showCommonDialog("未登记车辆");
                }else if(statusCode.equals("0003")){
                    showCommonDialog("解密失败");
                }else if(statusCode.equals(Constants.ERROR_CODE)){
                    showCommonDialog("服务异常，请稍后再试！");
                }
            }
        });
    }

    private void updateSystemInfo(ObuSystemInformation obuInfo) {

        ((SystemFragment)fragmentList.get(0)).updateUI(obuInfo);
    }


    /**
     * 激活操作
     */
    private void goActivation() {
        //
        String[] apdus =  new String[]{"0084000008"};
        int ret = MTSdkImp.getInstance(this).apduCommand(2,apdus.length,apdus);
        if(ret == 0){

            MyLog.d(MyLog.TAG," apdus[0] : " +  apdus[0]);
            if(!TextUtils.isEmpty(apdus[0])&&apdus[0].endsWith("9000")){
                // FFFF80D300 01 0A 7B9041A7F3A6DDEB 9000A6FF
                String rand = apdus[0].substring(0,16);
                MyLog.d(MyLog.TAG,"rand is : " + rand);
                String requestAactiveMac_data = obuSerialNum + rand + "04D6811A0501";
                requestAactiveMac("22",requestAactiveMac_data);
            }
        }
    }

    /**
     * 激活MAC计算请求
     * @param cmd   AST：0x22
     * @param data
     * DATA部分：
     * 字段	长度(字节)	说明
     * 分散因子	8	OBU合同序列号
     * MAC计算初始值	4	OBU返回的随机数
     * MAC计算数据	N	激活的COS命令
     */
    private void requestAactiveMac(String cmd,String data){
        showDialog("激活中...");
        SocketBusiness.getInstance().requestData(cmd,data,new RequestCallBack(){
            @Override
            public void next(String statusCode,String data) {
                dismissDialog();

                String writeCmd = "08B12710" +data.substring(0,8);
                writeMac(writeCmd);
            }

            @Override
            public void error(String statusCode,String error) {
                dismissDialog();
               /* 失败：错误码
                错误码类型：
                0x0001：MAC计算失败
                0x0002：尚未进行身份手持机认证
                0x0003：该车牌尚未登记
                0x0004：更新数据库失败*/


                if(statusCode.equals("0001")){
                    showCommonDialog("MAC计算失败");
                   // ToastUtils.showToast(IssueActivity.this,"MAC计算失败");
                }else if(statusCode.equals("0002")){
                    showCommonDialog("尚未进行身份手持机认证");
                }else if(statusCode.equals("0003")){
                    showCommonDialog("已激活过车辆，请重置！");
                }else if(statusCode.equals("0004")){
                    showCommonDialog("更新数据库失败");
                }else if(statusCode.equals(Constants.ERROR_CODE)){
                    showCommonDialog("服务异常，请稍后再试！");
                }
            }
        });
    }


    private void writeMac(String data){
        String[] apdus =  new String[]{data};
        int ret = MTSdkImp.getInstance(this).apduCommand(2,apdus.length,apdus);
        if(ret == 0){
            showCommonDialog("激活成功");
        }else{
            showCommonDialog("激活失败");
        }
    }
    private void initFragmentList() {
        if(fragmentList==null||fragmentList.size()<=0){
            fragmentList= new ArrayList<>();
            fragmentList.add(new SystemFragment());
            fragmentList.add(new CarFragment());
        }
    }

    private class  MyAdapter extends FragmentPagerAdapter {


        public MyAdapter(FragmentManager fm) {
            super(fm);
        }


        @Override
        public Fragment getItem(int i) {
            return fragmentList.get(i);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return titles[position];
        }
    }


    /**
     * 更多
     */
    @OnClick(R.id.more_iv)
    void showMore(){
        if(mPopView == null){
            View contentView = getLayoutInflater().inflate(
                    R.layout.layout_more_pop, null);
            new PopViewHolder(contentView);
            mPopView = new PopupWindow(contentView, CommonUtil.dip2px(this, 172), CommonUtil.dip2px(this, 176), true);
            mPopView.setOutsideTouchable(true);
            mPopView.setTouchInterceptor(new android.view.View.OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    return false;
                }
            });
            mPopView.setBackgroundDrawable(getResources().getDrawable(R.drawable.more_pop_bg));
        }
        if(mPopView.isShowing()){
            mPopView.dismiss();
        }else{
            mPopView.showAsDropDown(mMoreIv, -180, 0);
        }
    }

    public class PopViewHolder{
        public PopViewHolder(View view){
            ButterKnife.bind(this, view);
        }

        /**
         * 设置
         */
        @OnClick(R.id.pop_setting_bt)
        void setting(){
            startActivity(new Intent(IssueActivity.this, SettingActivity.class));
            if(mPopView.isShowing()){
                mPopView.dismiss();
            }
        }

        /**
         * 版本
         */
        @OnClick(R.id.pop_version_bt)
        void version(){
            startActivity(new Intent(IssueActivity.this, VersionActivity.class));
            if(mPopView.isShowing()){
                mPopView.dismiss();
            }
        }
    }

    //声明一个long类型变量：用于存放上一点击“返回键”的时刻
    private long mExitTime;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //判断用户是否点击了“返回键”
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            //与上次点击返回键时刻作差
            if ((System.currentTimeMillis() - mExitTime) > 2000) {
                //大于2000ms则认为是误操作，使用Toast进行提示
                Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
                //并记录下本次点击“返回键”的时刻，以便下次进行判断
                mExitTime = System.currentTimeMillis();
            } else {
                //小于2000ms则认为是用户确实希望退出程序-调用System.exit()方法进行退出
                ActivityTask.getInstance().onExit(this);
                // System.exit(0);
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
      //  BaseApplication.getInstance().powerOff();
    }
    /**
     * 检查网络是否可用
     *
     * @param context
     * @retur
     */
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
        if (mNetworkInfo != null) {
            // NetCheckBusiness.setNetState(mNetworkInfo.isAvailable());
            return mNetworkInfo.isAvailable()&&mNetworkInfo.isConnected();
        }
        return false;
    }
}
